﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Cesave.Domain.PermisosModule.Entities;
using Cesave.Infrastructure.CrossCutting.Logging;
using Cesave.Infrastructure.Data.PermisosModule.Context;
using Cesave.Domain.PermisosModule.Contracts.Distritos;
using Cesave.Infrastructure.Data.PermisosModule.Repositories;
using Cesave.Domain.Core.Specification;
using Cesave.Infrastructure.Data.PermisosModule.Mock;

namespace Cesave.Infrastructure.Data.PermisosModule.Tests.RepositoriesTests
{
	[TestClass]
	public class DistritoRepositoryTests
		: GenericRepositoryTestsBase<Distrito>
	{
		#region Overrides of GenericRepositoryTestsBase<Distrito>

		/// <summary>
		/// 
		/// </summary>
		public override System.Linq.Expressions.Expression<Func<Distrito, bool>> FilterExpression
		{
			get
			{
				return distrito => distrito.DistritoId == 11;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public override System.Linq.Expressions.Expression<Func<Distrito, int>> OrderByExpression
		{
			get
			{
				return distrito => distrito.DistritoId;
			}
		}

		#endregion

		[TestMethod]
		[ExpectedException(typeof(InvalidOperationException))]
		public void FindDistritosByEstadoSpecification_Zero_EstadoId_Throws_InvalidOperationException()
		{
			// Arrange
			IPermisosModuleContext context = GetContext();
			ITraceManager traceManager = GetTraceManager();
			IDistritoRepository repository = new DistritoRepository(context, traceManager);

			Guid estadoGuid = Guid.Empty;
			DistritosByEstadoSpecification specification = new DistritosByEstadoSpecification(estadoGuid);

			// Act
			var actual = repository.FindDistritosByEstadoSpecification(specification);
		}

		[TestMethod]
		[ExpectedException(typeof(ArgumentNullException))]
		public void FindDistritosByEstadoSpecification_Null_Specification_Throws_ArgumentNullException()
		{
			// Arrange
			IPermisosModuleContext context = GetContext();
			ITraceManager traceManager = GetTraceManager();
			IDistritoRepository repository = new DistritoRepository(context, traceManager);

			// Act
			var actual = repository.FindDistritosByEstadoSpecification(null);
		}

		[TestMethod]
		public void FindDistritosByEstadoSpecification_Invoke()
		{
			// Arrange
			IPermisosModuleContext context = GetContext();
			ITraceManager traceManager = GetTraceManager();
			IDistritoRepository repository = new DistritoRepository(context, traceManager);

			Guid estadoGuid = new Guid("B13F5C3F-AA42-4943-A8E9-49BA546EE5D1");
			DistritosByEstadoSpecification specification = new DistritosByEstadoSpecification(estadoGuid);

			// Act
			var actual = repository.FindDistritosByEstadoSpecification(specification);

			// Assert
			Assert.AreEqual(2, actual.Count());
			actual.ToList().ForEach(distrito =>
			{
				Assert.AreEqual(estadoGuid, distrito.EstadoGuid);
			});
		}

		[TestMethod]
		[ExpectedException(typeof(ArgumentNullException))]
		public void FindDistritosByEstadoAndStatusSpecification_Null_Specification_Throws_ArgumentNullException()
		{
			// Arrange
			IPermisosModuleContext context = GetContext();
			ITraceManager traceManager = GetTraceManager();
			IDistritoRepository repository = new DistritoRepository(context, traceManager);

			// Act
			var actual = repository.FindDistritosByEstadoAndStatusSpecification(null, null);
		}

		[TestMethod]
		public void FindDistritosByEstadoAndStatusSpecification_Invoke()
		{
			// Arrange
			IPermisosModuleContext context = GetContext();
			ITraceManager traceManager = GetTraceManager();
			IDistritoRepository repository = new DistritoRepository(context, traceManager);

			Guid estadoGuid = new Guid("B13F5C3F-AA42-4943-A8E9-49BA546EE5D1");
			bool status = true;
			DistritosByEstadoSpecification estadoSpecification = new DistritosByEstadoSpecification(estadoGuid);
			DistritosByStatusSpecification statusSpecification = new DistritosByStatusSpecification(status);

			// Act
			var actual = repository.FindDistritosByEstadoAndStatusSpecification(estadoSpecification, statusSpecification);

			// Assert
			Assert.AreEqual(2, actual.Count());
			actual.ToList().ForEach(distrito =>
			{
				Assert.AreEqual(estadoGuid, distrito.EstadoGuid);
				Assert.AreEqual(status, distrito.Status);
			});
		}

		[TestMethod]
		[ExpectedException(typeof(InvalidOperationException))]
		public void FindDistritoByGuidSpecification_Zero_DistritoId_Throws_InvalidOperationException()
		{
			// Arrange
			IPermisosModuleContext context = GetContext();
			ITraceManager traceManager = GetTraceManager();
			IDistritoRepository repository = new DistritoRepository(context, traceManager);

			Guid distritoGuid = Guid.Empty;
			DistritoByGuidSpecification specification = new DistritoByGuidSpecification(distritoGuid);

			// Act
			var actual = repository.FindDistritoByGuidSpecification(specification);
		}

		[TestMethod]
		[ExpectedException(typeof(ArgumentNullException))]
		public void FindDistritoByGuidSpecification_Null_Specification_Throws_ArgumentNullException()
		{
			// Arrange
			IPermisosModuleContext context = GetContext();
			ITraceManager traceManager = GetTraceManager();
			IDistritoRepository repository = new DistritoRepository(context, traceManager);

			DistritoByGuidSpecification specification = null;

			// Act
			var actual = repository.FindDistritoByGuidSpecification(specification);
		}

		/// <summary>
		/// TODO: Agregrar distritos a la base de datos.
		/// </summary>
		public void FindDistritoByIdSpecification_Invoke()
		{
			// Arrange
			//IPermisosModuleContext context = GetContext();
			//ITraceManager traceManager = GetTraceManager();
			//IDistritoRepository repository = new DistritoRepository(context, traceManager);

			//PermisosModuleFakeContext fakeContext = new PermisosModuleFakeContext();
			//Guid distritoGuid = fakeContext.Distrito149Guid;
			//DistritoByGuidSpecification specification = new DistritoByGuidSpecification(distritoGuid);

			// Act
			//var actual = repository.FindDistritoByGuidSpecification(specification);

			// Assert
			//Assert.IsNotNull(actual);
			//Assert.AreEqual(distritoGuid, actual.DistritoGuid);
		}

	}
}
